#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
备份管理器
负责数据库和配置文件的自动备份、定时备份和加密备份
"""

import os
import shutil
import zipfile
import logging
import threading
import time
import signal
import atexit
import sys
from datetime import datetime, timedelta
from pathlib import Path
from typing import Optional, List, Dict
import sqlite3
import json
from cryptography.fernet import Fernet
import base64

try:
    from ..utils.logger_manager import get_system_logger, OperationType, LogLevel
except ImportError:
    try:
        from src.utils.logger_manager import get_system_logger, OperationType, LogLevel
    except ImportError:
        get_system_logger = None
        OperationType = None
        LogLevel = None

logger = logging.getLogger(__name__)

# 全局备份状态变量，用于在多个实例间共享状态
_global_backup_status = {
    "emergency_backup_created": False,
    "close_backup_created": False,
    "backup_in_progress": False,
    "handlers_registered": False
}

_global_backup_lock = threading.Lock()

class BackupManager:
    """备份管理器"""
    
    def __init__(self, db_path: str, config_path: str, backup_path: str = None):
        """
        初始化备份管理器
        
        Args:
            db_path: 数据库文件路径
            config_path: 配置文件路径
            backup_path: 备份文件存储路径（可选，优先使用配置文件中的路径）
        """
        self.db_path = db_path
        self.config_path = config_path
        
        # 系统日志管理器
        self.system_logger = get_system_logger() if get_system_logger else None
        
        # 首先尝试从主配置文件读取备份路径
        if backup_path is None:
            try:
                from ..utils.config import Config
                config = Config(config_path)
                backup_path = config.get("backup.backup_path", "")
                if not backup_path:
                    # 如果配置文件中没有设置，使用默认路径
                    project_root = Path(__file__).parent.parent.parent
                    backup_path = str(project_root / "data" / "backups")
            except Exception as e:
                logger.warning(f"无法从配置文件读取备份路径: {e}")
                # 使用默认路径
                project_root = Path(__file__).parent.parent.parent
                backup_path = str(project_root / "data" / "backups")
        
        self.backup_path = Path(backup_path)
        self.backup_path.mkdir(parents=True, exist_ok=True)
        
        # 加密密钥
        self.encryption_key = None
        self.fernet = None
        
        # 备份配置 - 从主配置文件读取
        self.backup_config = self.load_config_from_main_config()
        
        # 定时备份线程
        self.backup_thread = None
        self.stop_backup = False
        
        # 异常退出备份相关
        self._emergency_backup_created = False
        self._close_backup_created = False  # 添加关闭备份状态标志
        self._backup_in_progress = False  # 添加备份进行中标志，防止并发备份
        self._backup_lock = threading.Lock()  # 添加线程锁，防止并发访问备份状态
        self._handlers_registered = False  # 添加处理器注册状态标志，防止重复注册
        self._last_checkpoint_time = datetime.now()
        self._checkpoint_interval = 300  # 5分钟检查一次
        
        # 初始化加密
        self.init_encryption()
        
        # 注册异常退出处理
        self._register_emergency_handlers()
        
        # 记录备份管理器初始化日志
        if self.system_logger:
            self.system_logger.log_system_event(
                "备份管理器初始化",
                "备份管理器已初始化完成",
                details={
                    "db_path": db_path,
                    "config_path": config_path,
                    "backup_path": str(self.backup_path),
                    "auto_backup": self.backup_config.get("auto_backup", True)
                }
            )
    
    def load_config_from_main_config(self):
        """从主配置文件加载备份配置"""
        try:
            from ..utils.config import Config
            config = Config(self.config_path)
            
            return {
                "auto_backup": config.get("backup.auto_backup", True),
                "auto_backup_interval": config.get("backup.auto_backup_interval", 24),
                "close_backup": config.get("backup.close_backup", True),
                "emergency_backup": config.get("backup.emergency_backup", True),
                "encryption_type": config.get("backup.encryption_type", "AES"),
                "max_backup_files": config.get("backup.max_backup_files", 30),
                "backup_database": config.get("backup.backup_database", True),
                "backup_config": config.get("backup.backup_config", True),
                "backup_logs": config.get("backup.backup_logs", True),
                "backup_path": config.get("backup.backup_path", str(self.backup_path)),
                "compression_level": config.get("backup.compression_level", 6),
                "include_temp_files": config.get("backup.include_temp_files", False)
            }
        except Exception as e:
            logger.error(f"从主配置文件加载备份配置失败: {e}")
            # 返回默认配置
            return {
                "auto_backup": True,
                "auto_backup_interval": 24,
                "close_backup": True,
                "emergency_backup": True,
                "encryption_type": "AES",
                "max_backup_files": 30,
                "backup_database": True,
                "backup_config": True,
                "backup_logs": True,
                "backup_path": str(self.backup_path),
                "compression_level": 6,
                "include_temp_files": False
            }
    
    def save_config_to_main_config(self, config_dict):
        """保存备份配置到主配置文件"""
        try:
            from ..utils.config import Config
            config = Config(self.config_path)
            
            # 更新备份配置
            for key, value in config_dict.items():
                config.set(f"backup.{key}", value)
            
            logger.info("备份配置已保存到主配置文件")
            return True
        except Exception as e:
            logger.error(f"保存备份配置到主配置文件失败: {e}")
            return False
    
    def init_encryption(self):
        """初始化加密功能"""
        try:
            if self.backup_config["encryption_type"] == "AES":
                # 从数据库获取或生成加密密钥
                from .database_manager import DatabaseManager
                db_manager = DatabaseManager()
                
                # 尝试从数据库获取备份加密密钥
                key_info = db_manager.get_encryption_key("backup_aes_key")
                
                if key_info:
                    # 使用数据库中的密钥
                    import base64
                    self.encryption_key = base64.b64decode(key_info["private_key"])
                    self.fernet = Fernet(self.encryption_key)
                    logger.info("从数据库加载加密密钥成功")
                else:
                    # 生成新的密钥并存储到数据库
                    self.encryption_key = Fernet.generate_key()
                    self.fernet = Fernet(self.encryption_key)
                    
                    # 将密钥存储到数据库
                    import base64
                    public_key_b64 = base64.b64encode(self.encryption_key).decode('utf-8')
                    private_key_b64 = base64.b64encode(self.encryption_key).decode('utf-8')
                    
                    success = db_manager.store_encryption_key(
                        key_name="backup_aes_key",
                        public_key=public_key_b64,
                        private_key=private_key_b64,
                        key_type="AES",
                        key_size=256,
                        description="备份文件AES-256加密密钥"
                    )
                    
                    if success:
                        logger.info("新加密密钥已生成并存储到数据库")
                    else:
                        logger.error("存储加密密钥到数据库失败")
                
                logger.info("加密功能初始化成功")
            else:
                logger.info("未启用加密功能")
        except Exception as e:
            logger.error(f"加密功能初始化失败: {e}")
            self.backup_config["encryption_type"] = "None"
    
    def update_backup_config(self, **kwargs):
        """更新备份配置"""
        # 检查异常退出备份配置是否发生变化
        emergency_backup_changed = (
            "emergency_backup" in kwargs and 
            kwargs["emergency_backup"] != self.backup_config.get("emergency_backup", True)
        )
        
        # 记录配置更新日志
        if self.system_logger:
            self.system_logger.log_system_event(
                "备份配置更新",
                "备份配置已更新",
                details={
                    "updated_configs": list(kwargs.keys()),
                    "new_values": kwargs
                }
            )
        
        self.backup_config.update(kwargs)
        
        # 保存到主配置文件
        self.save_config_to_main_config(self.backup_config)
        
        # 如果异常退出备份配置发生变化，重新注册处理器
        if emergency_backup_changed:
            logger.info("异常退出备份配置已更改，重新注册处理器")
            self._register_emergency_handlers()
        
        # 如果启用了定时备份，重新启动定时备份线程
        if self.backup_config["auto_backup"]:
            self.start_auto_backup()
    
    def create_backup(self, backup_name: str = None, include_logs: bool = True) -> Optional[str]:
        """
        创建备份
        
        Args:
            backup_name: 备份文件名，如果为None则自动生成
            include_logs: 是否包含日志文件
            
        Returns:
            备份文件路径，失败返回None
        """
        try:
            # 使用线程锁保护备份状态检查
            with _global_backup_lock:
                # 检查是否有备份正在进行中，防止并发备份
                if _global_backup_status["backup_in_progress"]:
                    logger.warning("备份正在进行中，跳过重复备份请求")
                    return None
                
                # 设置备份进行中标志
                _global_backup_status["backup_in_progress"] = True
            
            # 使用时间戳作为文件名前缀
            timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
            
            if backup_name is None:
                backup_name = f"{timestamp}_manual_backup"
            else:
                # 如果backup_name已经包含时间戳，直接使用
                if backup_name.startswith(timestamp):
                    pass  # 已经包含时间戳
                else:
                    # 添加时间戳前缀
                    backup_name = f"{timestamp}_{backup_name}"
            
            # 记录备份开始日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "备份开始",
                    f"开始创建备份: {backup_name}",
                    details={
                        "backup_name": backup_name,
                        "include_logs": include_logs,
                        "backup_config": self.backup_config
                    }
                )
            
            backup_dir = self.backup_path / backup_name
            backup_dir.mkdir(exist_ok=True)
            
            # 备份数据库
            if self.backup_config["backup_database"]:
                self._backup_database(backup_dir)
            
            # 备份配置文件
            if self.backup_config["backup_config"]:
                self._backup_config(backup_dir)
            
            # 备份日志文件
            if self.backup_config["backup_logs"] and include_logs:
                self._backup_logs(backup_dir)
            
            # 创建备份信息文件
            self._create_backup_info(backup_dir, backup_name)
            
            # 压缩备份目录
            zip_path = self._compress_backup(backup_dir, backup_name)
            
            # 如果启用加密，对压缩文件进行加密
            if self.backup_config["encryption_type"] == "AES" and self.fernet:
                zip_path = self._encrypt_file(zip_path)
            
            # 清理临时目录
            shutil.rmtree(backup_dir)
            
            # 清理旧备份文件
            self._cleanup_old_backups()
            
            logger.info(f"备份创建成功: {zip_path}")
            
            # 记录备份成功日志
            if self.system_logger:
                backup_size = os.path.getsize(zip_path) if os.path.exists(zip_path) else 0
                self.system_logger.log_system_event(
                    "备份完成",
                    f"备份创建成功: {backup_name}",
                    details={
                        "backup_name": backup_name,
                        "backup_path": str(zip_path),
                        "backup_size": backup_size,
                        "encryption_type": self.backup_config["encryption_type"]
                    }
                )
            
            return str(zip_path)
            
        except Exception as e:
            logger.error(f"创建备份失败: {e}")
            
            # 记录备份失败日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "备份失败",
                    f"创建备份失败: {backup_name}",
                    log_level=LogLevel.ERROR,
                    details={
                        "backup_name": backup_name,
                        "error": str(e),
                        "error_type": type(e).__name__
                    }
                )
            
            return None
        
        finally:
            # 使用线程锁保护状态重置
            with _global_backup_lock:
                # 重置备份进行中标志
                _global_backup_status["backup_in_progress"] = False
    
    def _backup_database(self, backup_dir: Path):
        """备份数据库文件"""
        try:
            if os.path.exists(self.db_path):
                # 创建数据库连接并执行VACUUM命令
                with sqlite3.connect(self.db_path) as conn:
                    conn.execute("VACUUM")
                
                # 复制数据库文件
                db_backup_path = backup_dir / "sample_management.db"
                shutil.copy2(self.db_path, db_backup_path)
                logger.info("数据库备份完成")
            else:
                logger.warning("数据库文件不存在，跳过备份")
        except Exception as e:
            logger.error(f"数据库备份失败: {e}")
    
    def _backup_config(self, backup_dir: Path):
        """备份配置文件"""
        try:
            if self.config_path and os.path.exists(self.config_path):
                config_backup_path = backup_dir / "config.json"
                shutil.copy2(self.config_path, config_backup_path)
                logger.info("配置文件备份完成")
            else:
                logger.warning("配置文件不存在或路径为空，跳过备份")
        except Exception as e:
            logger.error(f"配置文件备份失败: {e}")
    
    def _backup_logs(self, backup_dir: Path):
        """备份日志文件"""
        try:
            if self.config_path:
                log_dir = Path(self.config_path).parent / "logs"
            else:
                # 如果配置文件路径为空，使用默认路径
                project_root = Path(__file__).parent.parent.parent
                log_dir = project_root / "data" / "logs"
            
            if log_dir.exists():
                logs_backup_dir = backup_dir / "logs"
                shutil.copytree(log_dir, logs_backup_dir, dirs_exist_ok=True)
                logger.info("日志文件备份完成")
            else:
                logger.info("日志目录不存在，跳过备份")
        except Exception as e:
            logger.error(f"日志文件备份失败: {e}")
    
    def _create_backup_info(self, backup_dir: Path, backup_name: str):
        """创建备份信息文件"""
        try:
            backup_info = {
                "backup_name": backup_name,
                "backup_time": datetime.now().isoformat(),
                "backup_config": self.backup_config,
                "source_files": {
                    "database": self.db_path,
                    "config": self.config_path
                },
                "encryption_type": self.backup_config["encryption_type"]
            }
            
            info_file = backup_dir / "backup_info.json"
            with open(info_file, 'w', encoding='utf-8') as f:
                json.dump(backup_info, f, ensure_ascii=False, indent=2)
            
            logger.info("备份信息文件创建完成")
        except Exception as e:
            logger.error(f"创建备份信息文件失败: {e}")
    
    def _compress_backup(self, backup_dir: Path, backup_name: str) -> Path:
        """压缩备份目录"""
        try:
            zip_path = self.backup_path / f"{backup_name}.zip"
            
            with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
                for file_path in backup_dir.rglob('*'):
                    if file_path.is_file():
                        arcname = file_path.relative_to(backup_dir)
                        zipf.write(file_path, arcname)
            
            logger.info("备份压缩完成")
            return zip_path
        except Exception as e:
            logger.error(f"备份压缩失败: {e}")
            raise
    
    def _encrypt_file(self, file_path: Path) -> Path:
        """加密文件"""
        try:
            if not self.fernet:
                return file_path
            
            encrypted_path = file_path.with_suffix('.zip.encrypted')
            
            with open(file_path, 'rb') as f:
                data = f.read()
            
            encrypted_data = self.fernet.encrypt(data)
            
            with open(encrypted_path, 'wb') as f:
                f.write(encrypted_data)
            
            # 删除原文件
            file_path.unlink()
            
            logger.info("备份文件加密完成")
            return encrypted_path
        except Exception as e:
            logger.error(f"文件加密失败: {e}")
            return file_path
    
    def _cleanup_old_backups(self):
        """清理旧备份文件"""
        try:
            max_files = self.backup_config["max_backup_files"]
            if max_files <= 0:
                return
            
            # 获取所有备份文件
            backup_files = []
            for file_path in self.backup_path.glob("*.zip*"):
                if file_path.is_file():
                    backup_files.append((file_path, file_path.stat().st_mtime))
            
            # 按修改时间排序
            backup_files.sort(key=lambda x: x[1], reverse=True)
            
            # 删除超出数量限制的文件
            if len(backup_files) > max_files:
                for file_path, _ in backup_files[max_files:]:
                    file_path.unlink()
                    logger.info(f"删除旧备份文件: {file_path.name}")
        except Exception as e:
            logger.error(f"清理旧备份文件失败: {e}")
    
    def start_auto_backup(self):
        """启动自动备份"""
        if not self.backup_config["auto_backup"]:
            return
        
        if self.backup_thread and self.backup_thread.is_alive():
            return
        
        self.stop_backup = False
        self.backup_thread = threading.Thread(target=self._auto_backup_worker, daemon=True)
        self.backup_thread.start()
        logger.info("自动备份已启动")
    
    def stop_auto_backup(self):
        """停止自动备份"""
        self.stop_backup = True
        if self.backup_thread and self.backup_thread.is_alive():
            self.backup_thread.join(timeout=5)
        logger.info("自动备份已停止")
    
    def _auto_backup_worker(self):
        """自动备份工作线程"""
        while not self.stop_backup:
            try:
                # 等待指定的时间间隔
                time.sleep(self.backup_config["auto_backup_interval"] * 3600)
                
                if not self.stop_backup:
                    logger.info("执行定时备份")
                    self.create_backup()
                    
            except Exception as e:
                logger.error(f"自动备份失败: {e}")
                time.sleep(3600)  # 出错后等待1小时再试
    
    def restore_backup(self, backup_file: str, restore_path: str = None) -> bool:
        """
        恢复备份
        
        Args:
            backup_file: 备份文件路径
            restore_path: 恢复路径，如果为None则恢复到原位置
            
        Returns:
            恢复是否成功
        """
        try:
            backup_path = Path(backup_file)
            if not backup_path.exists():
                logger.error(f"备份文件不存在: {backup_file}")
                
                # 记录恢复失败日志
                if self.system_logger:
                    self.system_logger.log_system_event(
                        "备份恢复失败",
                        f"备份文件不存在: {backup_file}",
                        log_level=LogLevel.ERROR,
                        details={
                            "backup_file": backup_file,
                            "error": "备份文件不存在"
                        }
                    )
                
                return False
            
            # 记录恢复开始日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "备份恢复开始",
                    f"开始恢复备份: {backup_path.name}",
                    details={
                        "backup_file": backup_file,
                        "restore_path": restore_path,
                        "backup_size": backup_path.stat().st_size if backup_path.exists() else 0
                    }
                )
            
            # 如果是加密文件，先解密
            if backup_path.suffix == '.encrypted':
                backup_path = self._decrypt_file(backup_path)
            
            # 解压备份文件
            temp_dir = self.backup_path / "temp_restore"
            temp_dir.mkdir(exist_ok=True)
            
            with zipfile.ZipFile(backup_path, 'r') as zipf:
                zipf.extractall(temp_dir)
            
            # 读取备份信息
            backup_info = {}
            info_file = temp_dir / "backup_info.json"
            if info_file.exists():
                with open(info_file, 'r', encoding='utf-8') as f:
                    backup_info = json.load(f)
                    logger.info(f"恢复备份: {backup_info['backup_name']}")
            
            # 恢复文件
            if restore_path is None:
                restore_path = Path(self.config_path).parent
            
            restored_files = []
            
            # 恢复数据库
            db_backup = temp_dir / "sample_management.db"
            if db_backup.exists():
                db_restore_path = restore_path / "sample_management.db"
                shutil.copy2(db_backup, db_restore_path)
                restored_files.append("数据库")
                logger.info("数据库恢复完成")
            
            # 恢复配置文件
            config_backup = temp_dir / "config.json"
            if config_backup.exists():
                config_restore_path = restore_path / "config.json"
                shutil.copy2(config_backup, config_restore_path)
                restored_files.append("配置文件")
                logger.info("配置文件恢复完成")
            
            # 清理临时目录
            shutil.rmtree(temp_dir)
            
            logger.info("备份恢复完成")
            
            # 记录恢复成功日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "备份恢复完成",
                    f"备份恢复成功: {backup_path.name}",
                    details={
                        "backup_file": backup_file,
                        "restore_path": str(restore_path),
                        "restored_files": restored_files,
                        "backup_info": backup_info
                    }
                )
            
            return True
            
        except Exception as e:
            logger.error(f"恢复备份失败: {e}")
            
            # 记录恢复失败日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "备份恢复失败",
                    f"恢复备份失败: {backup_file}",
                    log_level=LogLevel.ERROR,
                    details={
                        "backup_file": backup_file,
                        "restore_path": restore_path,
                        "error": str(e),
                        "error_type": type(e).__name__
                    }
                )
            
            return False
    
    def _decrypt_file(self, encrypted_path: Path) -> Path:
        """解密文件"""
        try:
            if not self.fernet:
                return encrypted_path
            
            decrypted_path = encrypted_path.with_suffix('.zip')
            
            with open(encrypted_path, 'rb') as f:
                encrypted_data = f.read()
            
            decrypted_data = self.fernet.decrypt(encrypted_data)
            
            with open(decrypted_path, 'wb') as f:
                f.write(decrypted_data)
            
            logger.info("备份文件解密完成")
            return decrypted_path
        except Exception as e:
            logger.error(f"文件解密失败: {e}")
            return encrypted_path
    
    def get_backup_list(self) -> List[Dict]:
        """获取备份文件列表"""
        try:
            backup_list = []
            
            for file_path in self.backup_path.glob("*.zip*"):
                if file_path.is_file():
                    stat = file_path.stat()
                    backup_info = {
                        "name": file_path.name,
                        "path": str(file_path),
                        "size": stat.st_size,
                        "modified_time": datetime.fromtimestamp(stat.st_mtime).isoformat(),
                        "encrypted": file_path.suffix == '.encrypted'
                    }
                    
                    # 尝试读取备份信息
                    try:
                        if not backup_info["encrypted"]:
                            with zipfile.ZipFile(file_path, 'r') as zipf:
                                if "backup_info.json" in zipf.namelist():
                                    with zipf.open("backup_info.json") as f:
                                        info_data = json.load(f)
                                        backup_info.update(info_data)
                    except:
                        pass
                    
                    backup_list.append(backup_info)
            
            # 按修改时间排序
            backup_list.sort(key=lambda x: x["modified_time"], reverse=True)
            return backup_list
            
        except Exception as e:
            logger.error(f"获取备份列表失败: {e}")
            return []
    
    def close_backup(self):
        """程序关闭时执行备份"""
        try:
            logger.info("=== 开始程序关闭备份流程 ===")
            
            # 使用新的状态检查方法
            if not self._is_backup_needed():
                logger.info("备份已创建或正在进行中，跳过重复备份")
                return
            
            # 检查是否启用了关闭备份
            if not self.backup_config.get("close_backup", True):
                logger.info("程序关闭备份已禁用，跳过关闭备份")
                return
            
            logger.info("所有检查通过，程序关闭，执行自动备份")
            
            # 立即标记备份已创建，防止重复创建
            self._mark_backup_created("close")
            
            # 使用时间戳作为文件名前缀
            timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
            backup_name = f"{timestamp}_close_backup"
            
            # 创建备份
            backup_path = self.create_backup(backup_name)
            
            if backup_path:
                logger.info(f"程序关闭备份创建成功: {backup_path}")
            else:
                logger.error("程序关闭备份创建失败")
                # 如果创建失败，重置状态标志，允许重试
                with _global_backup_lock:
                    _global_backup_status["close_backup_created"] = False
                    logger.info("已重置关闭备份状态标志，允许重试")
                
        except Exception as e:
            logger.error(f"程序关闭备份失败: {e}")
            # 即使失败也要标记为已创建，避免重复尝试
            self._mark_backup_created("close")
        
        logger.info("=== 程序关闭备份流程结束 ===")
    
    def __del__(self):
        """析构函数"""
        self.stop_auto_backup() 
    
    def _register_emergency_handlers(self):
        """注册异常退出处理器"""
        try:
            # 只有在启用异常退出备份时才注册处理器
            if not self.backup_config.get("emergency_backup", True):
                logger.info("异常退出备份已禁用，不注册异常退出处理器")
                return
            
            # 检查是否已经注册过处理器，避免重复注册
            if _global_backup_status["handlers_registered"]:
                logger.info("异常退出处理器已注册，跳过重复注册")
                return
            
            # 注册信号处理器
            signal.signal(signal.SIGTERM, self._signal_handler)  # 终止信号
            signal.signal(signal.SIGINT, self._signal_handler)   # 中断信号 (Ctrl+C)
            
            # 在Windows上注册Ctrl+C处理器
            if hasattr(signal, 'SIGBREAK'):
                signal.signal(signal.SIGBREAK, self._signal_handler)  # Windows Ctrl+Break
            
            # 注册其他可能的信号
            if hasattr(signal, 'SIGABRT'):
                signal.signal(signal.SIGABRT, self._signal_handler)  # 异常终止
            
            if hasattr(signal, 'SIGFPE'):
                signal.signal(signal.SIGFPE, self._signal_handler)  # 浮点异常
            
            if hasattr(signal, 'SIGILL'):
                signal.signal(signal.SIGILL, self._signal_handler)  # 非法指令
            
            if hasattr(signal, 'SIGSEGV'):
                signal.signal(signal.SIGSEGV, self._signal_handler)  # 段错误
            
            # 注册程序退出时的清理函数（只注册一次）
            atexit.register(self._emergency_backup_on_exit)
            
            # 注册系统退出时的处理器（使用更兼容的方法）
            try:
                import threading
                if hasattr(threading, '_register_exit_handler'):
                    def exit_handler():
                        """系统退出处理器"""
                        try:
                            logger.info("=== 线程退出处理器被触发 ===")
                            
                            # 检查是否已经创建了任何类型的备份，避免重复备份
                            close_created = hasattr(self, '_close_backup_created') and self._close_backup_created
                            emergency_created = hasattr(self, '_emergency_backup_created') and self._emergency_backup_created
                            
                            logger.info(f"线程退出处理器状态检查 - 关闭备份: {close_created}, 紧急备份: {emergency_created}")
                            
                            if close_created or emergency_created:
                                logger.info("备份已创建，跳过线程退出处理器备份")
                                return
                            
                            logger.warning("系统退出，执行紧急备份")
                            self._create_emergency_backup()
                        except Exception as e:
                            logger.error(f"系统退出处理器失败: {e}")
                        
                        logger.info("=== 线程退出处理器结束 ===")
                    
                    # 注册线程退出处理器
                    threading._register_exit_handler(exit_handler)
                else:
                    logger.info("当前Python版本不支持threading._register_exit_handler，跳过注册")
            except Exception as e:
                logger.warning(f"注册系统退出处理器失败: {e}")
            
            # 标记处理器已注册
            _global_backup_status["handlers_registered"] = True
            logger.info("异常退出处理器注册成功")
            
        except Exception as e:
            logger.error(f"注册异常退出处理器失败: {e}")
    
    def _signal_handler(self, signum, frame):
        """信号处理器"""
        try:
            logger.info(f"=== 信号处理器被触发，信号: {signum} ===")
            
            # 检查是否已经创建了任何类型的备份，避免重复备份
            close_created = hasattr(self, '_close_backup_created') and self._close_backup_created
            emergency_created = hasattr(self, '_emergency_backup_created') and self._emergency_backup_created
            
            logger.info(f"信号处理器状态检查 - 关闭备份: {close_created}, 紧急备份: {emergency_created}")
            
            if close_created or emergency_created:
                logger.info("备份已创建，跳过信号处理器备份")
                sys.exit(0)
                return
            
            # 记录接收到的信号
            self._last_signal = signum
            signal_name = signal.Signals(signum).name if hasattr(signal, 'Signals') else str(signum)
            
            logger.warning(f"收到信号 {signal_name} ({signum})，执行紧急备份")
            
            # 立即创建紧急备份
            self._create_emergency_backup()
            
            # 等待一小段时间确保备份完成
            import time
            time.sleep(1)
            
            # 正常退出程序
            logger.info("信号处理完成，程序退出")
            sys.exit(0)
            
        except Exception as e:
            logger.error(f"信号处理失败: {e}")
            # 即使备份失败也要退出，避免程序卡死
            sys.exit(1)
        
        logger.info("=== 信号处理器结束 ===")
    
    def _emergency_backup_on_exit(self):
        """程序退出时的紧急备份"""
        try:
            logger.info("=== 程序退出处理器被触发 ===")
            
            # 检查是否已经创建了任何类型的备份，避免重复备份
            close_created = hasattr(self, '_close_backup_created') and self._close_backup_created
            emergency_created = hasattr(self, '_emergency_backup_created') and self._emergency_backup_created
            
            logger.info(f"退出处理器状态检查 - 关闭备份: {close_created}, 紧急备份: {emergency_created}")
            
            if close_created or emergency_created:
                logger.info("备份已创建，跳过紧急备份")
                return
            
            logger.warning("程序异常退出，执行紧急备份")
            self._create_emergency_backup()
        except Exception as e:
            logger.error(f"紧急备份失败: {e}")
        
        logger.info("=== 程序退出处理器结束 ===")
    
    def _create_emergency_backup(self):
        """创建紧急备份"""
        try:
            logger.info("=== 开始紧急备份创建流程 ===")
            
            # 使用新的状态检查方法
            if not self._is_backup_needed():
                logger.info("备份已创建或正在进行中，跳过重复创建")
                return
            
            # 检查是否启用了异常退出备份
            if not self.backup_config.get("emergency_backup", True):
                logger.info("异常退出备份已禁用，跳过紧急备份")
                return
            
            # 检查是否需要创建紧急备份
            if not self._should_create_emergency_backup():
                logger.info("无需创建紧急备份")
                return
            
            logger.info("所有检查通过，开始创建紧急备份")
            
            # 立即标记备份已创建，防止重复创建
            self._mark_backup_created("emergency")
            
            # 使用时间戳作为文件名前缀
            timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
            backup_name = f"{timestamp}_emergency_backup"
            
            # 创建备份（包含日志文件）
            backup_path = self.create_backup(backup_name, include_logs=True)
            
            if backup_path:
                logger.info(f"紧急备份创建成功: {backup_path}")
                
                # 记录紧急备份信息
                self._log_emergency_backup(backup_path)
            else:
                logger.error("紧急备份创建失败")
                # 如果创建失败，重置状态标志，允许重试
                with _global_backup_lock:
                    _global_backup_status["emergency_backup_created"] = False
                    logger.info("已重置紧急备份状态标志，允许重试")
                
        except Exception as e:
            logger.error(f"创建紧急备份失败: {e}")
            # 即使失败也要标记为已创建，避免重复尝试
            self._mark_backup_created("emergency")
        
        logger.info("=== 紧急备份创建流程结束 ===")
    
    def _should_create_emergency_backup(self) -> bool:
        """检查是否需要创建紧急备份"""
        try:
            # 使用线程锁保护状态检查
            with self._backup_lock:
                # 检查是否启用了异常退出备份
                if not self.backup_config.get("emergency_backup", True):
                    return False
                
                # 检查是否已经创建了任何类型的备份，避免重复备份
                if (hasattr(self, '_close_backup_created') and self._close_backup_created) or \
                   (hasattr(self, '_emergency_backup_created') and self._emergency_backup_created) or \
                   (hasattr(self, '_backup_in_progress') and self._backup_in_progress):
                    logger.info("备份已创建或正在进行中，跳过紧急备份")
                    return False
                
                # 检查是否启用了程序关闭备份（作为参考）
                if not self.backup_config.get("close_backup", True):
                    logger.info("程序关闭备份已禁用，跳过紧急备份")
                    return False
                
                # 检查距离上次检查点的时间间隔
                current_time = datetime.now()
                time_diff = current_time - self._last_checkpoint_time
                
                # 如果距离上次检查点超过设定时间，创建紧急备份
                if time_diff.total_seconds() > self._checkpoint_interval:
                    logger.info(f"距离上次检查点已超过 {self._checkpoint_interval} 秒，需要创建紧急备份")
                    return True
                
                # 检查是否有未保存的重要数据
                if self._has_unsaved_changes():
                    logger.info("检测到未保存的更改，需要创建紧急备份")
                    return True
                
                # 检查是否有最近的备份
                if self._should_backup_based_on_recent_activity():
                    logger.info("检测到最近的活动，需要创建紧急备份")
                    return True
                
                logger.info("无需创建紧急备份")
                return False
                
        except Exception as e:
            logger.error(f"检查紧急备份条件失败: {e}")
            # 出错时默认创建备份，确保数据安全
            return True
    
    def _has_unsaved_changes(self) -> bool:
        """检查是否有未保存的更改"""
        try:
            # 检查数据库是否有未提交的事务
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute("SELECT COUNT(*) FROM sqlite_master WHERE type='table'")
                table_count = cursor.fetchone()[0]
                
                # 如果有表，检查是否有最近的活动
                if table_count > 0:
                    # 检查最近的样本记录
                    cursor.execute("""
                        SELECT COUNT(*) FROM lis_samples 
                        WHERE receive_time > datetime('now', '-1 hour')
                    """)
                    recent_samples = cursor.fetchone()[0]
                    
                    # 检查最近的操作日志
                    cursor.execute("""
                        SELECT COUNT(*) FROM operation_logs 
                        WHERE operation_time > datetime('now', '-1 hour')
                    """)
                    recent_logs = cursor.fetchone()[0]
                    
                    return recent_samples > 0 or recent_logs > 0
            
            return False
            
        except Exception as e:
            logger.error(f"检查未保存更改失败: {e}")
            return True  # 出错时假设有未保存的更改
    
    def delete_backup(self, backup_file: str) -> bool:
        """
        删除备份文件
        
        Args:
            backup_file: 备份文件路径或文件名
            
        Returns:
            删除是否成功
        """
        try:
            # 如果只提供了文件名，构建完整路径
            if not os.path.isabs(backup_file):
                backup_path = self.backup_path / backup_file
            else:
                backup_path = Path(backup_file)
            
            if not backup_path.exists():
                logger.error(f"备份文件不存在: {backup_file}")
                
                # 记录删除失败日志
                if self.system_logger:
                    self.system_logger.log_system_event(
                        "备份删除失败",
                        f"备份文件不存在: {backup_file}",
                        log_level=LogLevel.ERROR,
                        details={
                            "backup_file": backup_file,
                            "error": "备份文件不存在"
                        }
                    )
                
                return False
            
            # 获取文件信息用于日志记录
            file_size = backup_path.stat().st_size
            file_modified = datetime.fromtimestamp(backup_path.stat().st_mtime)
            
            # 记录删除开始日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "备份删除开始",
                    f"开始删除备份: {backup_path.name}",
                    details={
                        "backup_file": str(backup_path),
                        "file_size": file_size,
                        "file_modified": file_modified.isoformat()
                    }
                )
            
            # 删除文件
            backup_path.unlink()
            
            logger.info(f"备份文件删除成功: {backup_path.name}")
            
            # 记录删除成功日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "备份删除完成",
                    f"备份删除成功: {backup_path.name}",
                    details={
                        "backup_file": str(backup_path),
                        "file_size": file_size,
                        "file_modified": file_modified.isoformat()
                    }
                )
            
            return True
            
        except Exception as e:
            logger.error(f"删除备份文件失败: {e}")
            
            # 记录删除失败日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "备份删除失败",
                    f"删除备份失败: {backup_file}",
                    log_level=LogLevel.ERROR,
                    details={
                        "backup_file": backup_file,
                        "error": str(e),
                        "error_type": type(e).__name__
                    }
                )
            
            return False
    
    def delete_multiple_backups(self, backup_files: List[str]) -> Dict[str, bool]:
        """
        批量删除备份文件
        
        Args:
            backup_files: 备份文件路径列表
            
        Returns:
            删除结果字典，键为文件路径，值为是否删除成功
        """
        results = {}
        
        # 记录批量删除开始日志
        if self.system_logger:
            self.system_logger.log_system_event(
                "批量备份删除开始",
                f"开始批量删除 {len(backup_files)} 个备份文件",
                details={
                    "backup_files": backup_files,
                    "total_count": len(backup_files)
                }
            )
        
        for backup_file in backup_files:
            results[backup_file] = self.delete_backup(backup_file)
        
        # 统计删除结果
        success_count = sum(1 for success in results.values() if success)
        failed_count = len(results) - success_count
        
        # 记录批量删除完成日志
        if self.system_logger:
            self.system_logger.log_system_event(
                "批量备份删除完成",
                f"批量删除完成: 成功 {success_count}, 失败 {failed_count}, 总计 {len(backup_files)}",
                details={
                    "total_count": len(backup_files),
                    "success_count": success_count,
                    "failed_count": failed_count,
                    "results": results
                }
            )
        
        return results
    
    def _should_backup_based_on_recent_activity(self) -> bool:
        """基于最近活动判断是否需要备份"""
        try:
            # 检查最近的备份文件
            backup_files = list(self.backup_path.glob("*.zip*"))
            if not backup_files:
                # 如果没有备份文件，需要创建
                return True
            
            # 获取最新的备份文件时间
            latest_backup_time = max(f.stat().st_mtime for f in backup_files)
            latest_backup_datetime = datetime.fromtimestamp(latest_backup_time)
            
            # 如果距离上次备份超过2小时，建议创建备份
            current_time = datetime.now()
            time_diff = current_time - latest_backup_datetime
            
            if time_diff.total_seconds() > 7200:  # 2小时
                return True
            
            return False
            
        except Exception as e:
            logger.error(f"检查最近活动失败: {e}")
            return True  # 出错时建议创建备份
    
    def _log_emergency_backup(self, backup_path: str):
        """记录紧急备份信息"""
        try:
            emergency_log = {
                "timestamp": datetime.now().isoformat(),
                "backup_path": backup_path,
                "backup_type": "emergency",
                "reason": "程序异常退出",
                "system_info": {
                    "platform": sys.platform,
                    "python_version": sys.version,
                    "signal_received": getattr(self, '_last_signal', None)
                }
            }
            
            # 保存紧急备份日志
            log_file = self.backup_path / "emergency_backup_log.json"
            with open(log_file, 'w', encoding='utf-8') as f:
                json.dump(emergency_log, f, ensure_ascii=False, indent=2)
            
            logger.info("紧急备份日志已记录")
            
        except Exception as e:
            logger.error(f"记录紧急备份日志失败: {e}")
    
    def update_checkpoint(self):
        """更新检查点时间"""
        self._last_checkpoint_time = datetime.now()
    
    def set_checkpoint_interval(self, interval_seconds: int):
        """设置检查点间隔"""
        self._checkpoint_interval = interval_seconds
    
    def _is_backup_needed(self) -> bool:
        """检查是否需要进行任何类型的备份"""
        try:
            with _global_backup_lock:
                # 记录当前备份状态，用于调试
                close_created = _global_backup_status["close_backup_created"]
                emergency_created = _global_backup_status["emergency_backup_created"]
                backup_in_progress = _global_backup_status["backup_in_progress"]
                
                logger.debug(f"备份状态检查 - 关闭备份: {close_created}, 紧急备份: {emergency_created}, 进行中: {backup_in_progress}")
                
                # 如果任何类型的备份已创建或正在进行中，则不需要备份
                if close_created or emergency_created or backup_in_progress:
                    logger.info(f"备份已创建或正在进行中，跳过备份 - 关闭: {close_created}, 紧急: {emergency_created}, 进行中: {backup_in_progress}")
                    return False
                
                logger.debug("备份状态检查通过，可以进行备份")
                return True
        except Exception as e:
            logger.error(f"检查备份状态失败: {e}")
            return False
    
    def _mark_backup_created(self, backup_type: str):
        """标记备份已创建"""
        try:
            with _global_backup_lock:
                if backup_type == "close":
                    _global_backup_status["close_backup_created"] = True
                    logger.info(f"已标记关闭备份为已创建，状态: {_global_backup_status['close_backup_created']}")
                elif backup_type == "emergency":
                    _global_backup_status["emergency_backup_created"] = True
                    logger.info(f"已标记紧急备份为已创建，状态: {_global_backup_status['emergency_backup_created']}")
                else:
                    logger.warning(f"未知的备份类型: {backup_type}")
                
                # 记录当前所有备份状态
                close_created = _global_backup_status["close_backup_created"]
                emergency_created = _global_backup_status["emergency_backup_created"]
                backup_in_progress = _global_backup_status["backup_in_progress"]
                logger.info(f"备份状态更新后 - 关闭: {close_created}, 紧急: {emergency_created}, 进行中: {backup_in_progress}")
                
        except Exception as e:
            logger.error(f"标记备份状态失败: {e}")
    
    def get_backup_status(self) -> dict:
        """获取当前备份状态，用于调试"""
        try:
            with _global_backup_lock:
                return {
                    "close_backup_created": _global_backup_status["close_backup_created"],
                    "emergency_backup_created": _global_backup_status["emergency_backup_created"],
                    "backup_in_progress": _global_backup_status["backup_in_progress"],
                    "handlers_registered": _global_backup_status["handlers_registered"],
                    "last_checkpoint_time": getattr(self, '_last_checkpoint_time', None),
                    "checkpoint_interval": getattr(self, '_checkpoint_interval', None)
                }
        except Exception as e:
            logger.error(f"获取备份状态失败: {e}")
            return {}
    
    def reset_backup_status(self):
        """重置所有备份状态，用于调试"""
        try:
            with _global_backup_lock:
                _global_backup_status["close_backup_created"] = False
                _global_backup_status["emergency_backup_created"] = False
                _global_backup_status["backup_in_progress"] = False
                _global_backup_status["handlers_registered"] = False
                logger.warning("已重置所有备份状态标志")
        except Exception as e:
            logger.error(f"重置备份状态失败: {e}") 